package com.atguigu.day1;


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 2.判断/干活/通知
 * 3.在多线程通信编码中，一定要防止----虚假唤醒，也不能出现虚假换新情况
 */

class AirCondition {
    int number = 0;

    //使用synchnorized方法
/*    public synchronized void increment() {
        //判断
        while (number != 0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        //干活
        System.out.println(Thread.currentThread().getName() + "\t" + (++number));
        //通知
        this.notifyAll();
    }
    public synchronized void decrement() {
        //判断
        while (number == 0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        //干活
        System.out.println(Thread.currentThread().getName() + "\t" + (--number));
        //通知
        this.notifyAll();
    }*/

    //使用Lock方法
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void increment(){
        lock.lock();
        try {
            //判断
            while (number != 0 ){
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            //干活
            System.out.println(Thread.currentThread().getName() + "\t" + (++number));
            //通知
            condition.signal();
        }finally {
            lock.unlock();
        }
    }
    public void decrement(){
        lock.lock();
        try {
            //判断,需要用While循环来判断，每次唤醒后都需要再判断一次再往下执行，避免执行多次相同的方法
            while (number == 0){
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            //干活
            System.out.println(Thread.currentThread().getName() + "\t" + (--number));
            //通知
            condition.signal();
        }finally {
            lock.unlock();
        }
    }

}

public class ProdConsunmerDemo {

    public static void main(String[] args) {
        AirCondition airCondition = new AirCondition();

        //两个线程交替操作
        /*new Thread(() -> {
            for (int i = 0; i < 11; i++) {
                airCondition.increment();
            }
        }, "a").start();
        new Thread(() -> {
            for (int i = 0; i < 11; i++) {
                airCondition.decrement();
            }
        }, "b").start();*/

        //四个线程交替操作
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                airCondition.increment();
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                airCondition.decrement();
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                airCondition.increment();
            }
        }, "C").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                airCondition.decrement();
            }
        }, "D").start();
    }

}
